<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>线索管理 - 百日行动线索收集系统</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
    <link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.7.2/font/bootstrap-icons.css" rel="stylesheet">
    <link href="css/admin-mobile.css" rel="stylesheet">
    <style>
        body {
            background-color: #f8f9fa;
        }
        .sidebar {
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            min-height: 100vh;
            position: fixed;
            top: 0;
            left: 0;
            width: 250px;
            z-index: 1000;
        }
        .sidebar .nav-link {
            color: rgba(255, 255, 255, 0.8);
            padding: 12px 20px;
            border-radius: 8px;
            margin: 2px 10px;
            transition: all 0.3s ease;
        }
        .sidebar .nav-link:hover,
        .sidebar .nav-link.active {
            background: rgba(255, 255, 255, 0.2);
            color: white;
        }
        .main-content {
            margin-left: 250px;
            padding: 20px;
        }
        .navbar {
            background: white;
            box-shadow: 0 2px 4px rgba(0,0,0,0.1);
            margin-bottom: 20px;
        }
        .filter-card {
            background: white;
            border-radius: 15px;
            padding: 20px;
            box-shadow: 0 5px 15px rgba(0,0,0,0.08);
            margin-bottom: 20px;
        }
        .clue-table {
            background: white;
            border-radius: 15px;
            padding: 20px;
            box-shadow: 0 5px 15px rgba(0,0,0,0.08);
        }
        .status-badge {
            font-size: 12px;
            padding: 4px 8px;
            border-radius: 20px;
        }
        .status-pending { background: #fff3cd; color: #856404; }
        .status-processing { background: #d1ecf1; color: #0c5460; }
        .status-completed { background: #d4edda; color: #155724; }
        .status-closed { background: #f8d7da; color: #721c24; }
        .priority-high { color: #dc3545; }
        .priority-medium { color: #ffc107; }
        .priority-low { color: #28a745; }
        .table th {
            border-top: none;
            font-weight: 600;
            color: #495057;
        }
        .btn-action {
            padding: 4px 8px;
            font-size: 12px;
            margin: 2px;
        }
        .attachment-grid {
            display: grid;
            grid-template-columns: repeat(3, minmax(0, 1fr));
            gap: 15px;
        }
        
        .attachment-item {
            border: 1px solid #dee2e6;
            border-radius: 8px;
            padding: 15px;
            background: #f8f9fa;
        }
        
        .card.h-100 {
            min-width: 0;
            word-break: break-all;
            overflow-wrap: anywhere;
        }
        .card-title, .card-text, .card-body, .btn-group, .card {
            word-break: break-all;
            overflow-wrap: anywhere;
        }
        .card-title {
            font-size: 1rem;
            white-space: normal;
            max-width: 100%;
            overflow: hidden;
            text-overflow: ellipsis;
        }
        .card-text {
            font-size: 0.95rem;
            white-space: normal;
            max-width: 100%;
        }
        .btn-group {
            flex-wrap: wrap;
            gap: 4px;
        }
        .card-body {
            padding: 1rem;
        }
        .img-thumbnail, video, audio {
            max-width: 100%;
            height: auto;
            display: block;
            margin: 0 auto;
        }
        @media (max-width: 768px) {
            .attachment-grid {
                grid-template-columns: 1fr;
            }
            .card-body {
                padding: 0.5rem;
            }
        }
        
        /* 选中状态样式 */
        .clue-checkbox:checked + .clue-row {
            background-color: rgba(13, 110, 253, 0.1);
        }
        
        .selected-count-info {
            font-size: 0.875rem;
            color: #6c757d;
        }
        
        .export-dropdown .dropdown-item.disabled {
            opacity: 0.6;
            pointer-events: none;
        }
        
        .batch-actions {
            transition: opacity 0.3s ease;
        }
        
        .batch-actions.has-selection {
            opacity: 1;
        }
        
        .batch-actions:not(.has-selection) {
            opacity: 0.7;
        }
        
        /* 时间线样式 */
        .timeline {
            position: relative;
            padding-left: 30px;
        }
        
        .timeline::before {
            content: '';
            position: absolute;
            left: 15px;
            top: 0;
            bottom: 0;
            width: 2px;
            background: #dee2e6;
        }
        
        .timeline-item {
            position: relative;
            margin-bottom: 20px;
        }
        
        .timeline-marker {
            position: absolute;
            left: -22px;
            top: 5px;
            width: 30px;
            height: 30px;
            border-radius: 50%;
            background: #fff;
            border: 2px solid #007bff;
            display: flex;
            align-items: center;
            justify-content: center;
            font-size: 12px;
            color: #007bff;
        }
        
        .timeline-content {
            background: #f8f9fa;
            border: 1px solid #dee2e6;
            border-radius: 8px;
            padding: 15px;
            margin-left: 15px;
        }
        
        .timeline-content h6 {
            color: #495057;
            margin-bottom: 8px;
        }
        
        .timeline-item:last-child .timeline-marker {
            border-color: #28a745;
            color: #28a745;
        }
        
        /* 响应式调整 */
        @media (max-width: 768px) {
            .timeline {
                padding-left: 20px;
            }
            
            .timeline-marker {
                left: -15px;
                width: 24px;
                height: 24px;
                font-size: 10px;
            }
            
            .timeline-content {
                margin-left: 10px;
                padding: 10px;
            }
        }
    </style>
</head>
<body>
    <!-- 移动端头部 -->
    <div class="mobile-header">
        <button class="mobile-menu-btn" id="mobileMenuBtn">
            <i class="bi bi-list"></i>
        </button>
        <h5 class="mb-0">线索管理</h5>
        <div class="dropdown">
            <button class="btn btn-link dropdown-toggle" type="button" data-bs-toggle="dropdown">
                <i class="bi bi-person-circle"></i>
            </button>
            <ul class="dropdown-menu dropdown-menu-end">
                <li><a class="dropdown-item" href="#"><i class="bi bi-person me-2"></i>个人资料</a></li>
                <li><hr class="dropdown-divider"></li>
                <li><a class="dropdown-item logout-btn" href="#"><i class="bi bi-box-arrow-right me-2"></i>退出登录</a></li>
            </ul>
        </div>
    </div>
    
    <!-- 侧边栏遮罩层 -->
    <div class="sidebar-overlay"></div>
    
    <!-- 侧边栏 -->
    <nav class="sidebar" id="sidebar">
        <div class="p-3">
            <h5 class="text-white mb-4">
                <i class="bi bi-shield-check me-2"></i>
                管理后台
            </h5>
            <ul class="nav flex-column">
                <li class="nav-item">
                    <a class="nav-link" href="dashboard.html">
                        <i class="bi bi-speedometer2 me-2"></i>仪表板
                    </a>
                </li>
                <li class="nav-item">
                    <a class="nav-link active" href="clues.html">
                        <i class="bi bi-file-text me-2"></i>线索管理
                    </a>
                </li>
                <li class="nav-item">
                    <a class="nav-link" href="statistics.html">
                        <i class="bi bi-bar-chart me-2"></i>统计分析
                    </a>
                </li>
                <li class="nav-item">
                    <a class="nav-link" href="users.html">
                        <i class="bi bi-people me-2"></i>用户管理
                    </a>
                </li>
                <li class="nav-item">
                    <a class="nav-link" href="settings.html">
                        <i class="bi bi-gear me-2"></i>系统设置
                    </a>
                </li>
            </ul>
        </div>
        <div class="mt-auto p-3">
            <button class="btn btn-outline-light btn-sm w-100 logout-btn">
                <i class="bi bi-box-arrow-right me-2"></i>退出登录
            </button>
        </div>
    </nav>

    <!-- 主内容区 -->
    <div class="main-content">
        <!-- 顶部导航 -->
        <nav class="navbar navbar-expand-lg navbar-light">
            <div class="container-fluid">
                <h4 class="mb-0">线索管理</h4>
                <div class="navbar-nav ms-auto">
                    <div class="nav-item dropdown">
                        <a class="nav-link dropdown-toggle" href="#" id="userDropdown" role="button" data-bs-toggle="dropdown">
                            <i class="bi bi-person-circle me-2"></i>
                            <span id="adminName">管理员</span>
                        </a>
                        <ul class="dropdown-menu">
                            <li><a class="dropdown-item" href="#"><i class="bi bi-person me-2"></i>个人资料</a></li>
                            <li><hr class="dropdown-divider"></li>
                            <li><a class="dropdown-item logout-btn" href="#"><i class="bi bi-box-arrow-right me-2"></i>退出登录</a></li>
                        </ul>
                    </div>
                </div>
            </div>
        </nav>

        <!-- 筛选区域 -->
        <div class="filter-card">
            <div class="row g-3">
                <div class="col-md-3">
                    <label class="form-label">状态筛选</label>
                    <select class="form-select" id="statusFilter">
                        <option value="">全部状态</option>
                        <option value="pending">待处理</option>
                        <option value="processing">处理中</option>
                        <option value="completed">已完成</option>
                        <option value="closed">已关闭</option>
                    </select>
                </div>
                <div class="col-md-3">
                    <label class="form-label">线索分类</label>
                    <select class="form-select" id="categoryFilter">
                        <option value="">全部分类</option>
                    </select>
                </div>
                <div class="col-md-3">
                    <label class="form-label">优先级</label>
                    <select class="form-select" id="priorityFilter">
                        <option value="">全部优先级</option>
                        <option value="3">高</option>
                        <option value="2">中</option>
                        <option value="1">低</option>
                    </select>
                </div>
                <div class="col-md-3">
                    <label class="form-label">关键词搜索</label>
                    <div class="input-group">
                        <input type="text" class="form-control" id="keywordSearch" placeholder="搜索标题、内容...">
                        <button class="btn btn-primary" onclick="searchClues()">
                            <i class="bi bi-search"></i>
                        </button>
                    </div>
                </div>
            </div>
            <div class="row mt-3 g-3">
                <div class="col-md-3">
                    <label class="form-label">开始时间</label>
                    <input type="datetime-local" class="form-control" id="startDateFilter">
                </div>
                <div class="col-md-3">
                    <label class="form-label">结束时间</label>
                    <input type="datetime-local" class="form-control" id="endDateFilter">
                </div>
                <div class="col-md-3">
                </div>
                <div class="col-md-3 d-flex align-items-end">
                    <button class="btn btn-outline-secondary" id="resetFiltersBtn">
                        <i class="bi bi-arrow-clockwise me-2"></i>重置筛选
                    </button>
                </div>
            </div>
            <div class="row mt-3">
                <div class="col-md-6">
                    <button class="btn btn-primary" id="exportBtn" onclick="exportSelectedClues()">
                        <i class="bi bi-download me-2"></i>导出选中数据 <span class="badge bg-light text-dark ms-1" id="selectedCountBadge">0</span>
                    </button>
                </div>
                <div class="col-md-6 text-end">
                    <div class="btn-group batch-actions" id="batchActionsGroup">
                        <button class="btn btn-outline-secondary btn-sm" onclick="clearSelection()" title="清空选择" id="clearSelectionBtn" style="display: none;">
                            <i class="bi bi-x-square me-1"></i>清空选择 <span class="badge bg-light text-dark ms-1" id="clearSelectionBadge">0</span>
                        </button>
                        <button class="btn btn-outline-warning" onclick="batchUpdateStatus('processing')">
                            <i class="bi bi-arrow-repeat me-2"></i>批量处理中
                        </button>
                        <button class="btn btn-outline-success" onclick="batchUpdateStatus('completed')">
                            <i class="bi bi-check-circle me-2"></i>批量完成
                        </button>
                    </div>
                </div>
            </div>
        </div>

        <!-- 线索列表 -->
        <div class="clue-table">
            <div class="d-flex justify-content-between align-items-center mb-3">
                <div>
                <h5 class="mb-0">线索列表</h5>
                    <small class="text-muted">
                        <i class="bi bi-info-circle me-1"></i>
                        提示：勾选线索后可使用"导出选中数据"功能，或使用批量操作
                    </small>
                </div>
                <div class="d-flex align-items-center">
                    <span class="text-muted me-3">共 <span id="totalCount">0</span> 条线索</span>
                    <select class="form-select form-select-sm" style="width: auto;" id="pageSizeSelect" onchange="changePageSize()">
                        <option value="10">10条/页</option>
                        <option value="20" selected>20条/页</option>
                        <option value="50">50条/页</option>
                    </select>
                </div>
            </div>

            <div class="table-responsive">
                <table class="table table-hover">
                    <thead>
                        <tr>
                            <th width="40">
                                <input type="checkbox" id="selectAll">
                            </th>
                            <th>线索编号</th>
                            <th>标题</th>
                            <th>分类</th>
                            <th>状态</th>
                            <th>优先级</th>
                            <th>举报人</th>
                            <th>提交时间</th>
                            <th>处理人</th>
                            <th width="200">操作</th>
                        </tr>
                    </thead>
                    <tbody id="clueTableBody">
                        <!-- 动态加载 -->
                    </tbody>
                </table>
            </div>

            <!-- 分页 -->
            <nav aria-label="分页导航">
                <ul class="pagination justify-content-center" id="pagination">
                    <!-- 动态生成 -->
                </ul>
            </nav>
        </div>
    </div>

    <!-- 线索详情模态框 -->
    <div class="modal fade" id="clueDetailModal" tabindex="-1">
        <div class="modal-dialog modal-lg">
            <div class="modal-content">
                <div class="modal-header">
                    <h5 class="modal-title">线索详情</h5>
                    <button type="button" class="btn-close" data-bs-dismiss="modal"></button>
                </div>
                <div class="modal-body" id="clueDetailContent">
                    <!-- 动态加载 -->
                </div>
                <div class="modal-footer">
                    <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">关闭</button>
                    <button type="button" class="btn btn-primary" onclick="editClue()">编辑处理</button>
                </div>
            </div>
        </div>
    </div>

    <!-- 状态更新模态框 -->
    <div class="modal fade" id="statusUpdateModal" tabindex="-1">
        <div class="modal-dialog">
            <div class="modal-content">
                <div class="modal-header">
                    <h5 class="modal-title">更新线索状态</h5>
                    <button type="button" class="btn-close" data-bs-dismiss="modal"></button>
                </div>
                <div class="modal-body">
                    <form id="statusUpdateForm">
                        <input type="hidden" id="updateClueId">
                        <div class="mb-3">
                            <label class="form-label">新状态</label>
                            <select class="form-select" id="newStatus" required>
                                <option value="pending">待处理</option>
                                <option value="processing">处理中</option>
                                <option value="completed">已完成</option>
                                <option value="closed">已关闭</option>
                            </select>
                        </div>
                        <div class="mb-3">
                            <label class="form-label">处理意见 <span class="text-muted">(可选)</span></label>
                            <textarea class="form-control" id="handleNote" rows="4" placeholder="请输入处理意见、处理结果或备注信息..."></textarea>
                            <div class="form-text">
                                <small class="text-muted">处理意见将记录在线索历史中，便于后续跟踪和审查</small>
                        </div>
                        </div>
                        <div id="statusUpdateResult" class="alert" style="display: none;"></div>
                    </form>
                </div>
                <div class="modal-footer">
                    <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button>
                    <button type="button" class="btn btn-primary" id="confirmUpdateBtn" onclick="submitStatusUpdate()">确认更新</button>
                </div>
            </div>
        </div>
    </div>

    <!-- 处理历史模态框 -->
    <div class="modal fade" id="processingHistoryModal" tabindex="-1">
        <div class="modal-dialog modal-lg">
            <div class="modal-content">
                <div class="modal-header">
                    <h5 class="modal-title">处理历史</h5>
                    <button type="button" class="btn-close" data-bs-dismiss="modal"></button>
                </div>
                <div class="modal-body" id="processingHistoryContent">
                    <!-- 动态加载 -->
                </div>
                <div class="modal-footer">
                    <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">关闭</button>
                </div>
            </div>
        </div>
    </div>

    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
    <script src="js/admin-mobile.js"></script>
    <script>
        // 全局变量
        let currentPage = 1;
        let pageSize = 20;
        let totalPages = 1;
        let selectedClues = [];
        let currentClueId = null;

        // 页面加载完成后初始化
        document.addEventListener('DOMContentLoaded', function() {
            checkAuth();
            loadCategories();
            loadClues();
            
            // 初始化选中计数显示
            updateSelectedCountDisplay();
            
            // 绑定全选复选框事件
            const selectAllCheckbox = document.getElementById('selectAll');
            if (selectAllCheckbox) {
                selectAllCheckbox.addEventListener('change', function() {
                    console.log('全选复选框状态变化:', this.checked);
                    toggleSelectAll();
                });
            }

            // 绑定移动端菜单按钮
            const mobileMenuBtn = document.getElementById('mobileMenuBtn');
            if (mobileMenuBtn) {
                mobileMenuBtn.addEventListener('click', function() {
                    if (typeof toggleSidebar === 'function') toggleSidebar();
                });
            }

            // 绑定所有退出登录按钮
            document.querySelectorAll('.logout-btn').forEach(btn => {
                btn.addEventListener('click', function(e) {
                    e.preventDefault();
                    logout();
                });
            });

            // 添加测试函数到全局作用域
            window.testSetClueStatus = function(clueId, status) {
                console.log('测试setClueStatus被调用:', { clueId, status });
                setClueStatus(clueId, status);
            };
            
            window.testSetPriority = function(clueId, priority) {
                console.log('测试setPriority被调用:', { clueId, priority });
                setPriority(clueId, priority);
            };
            
            // 绑定筛选器事件
            document.getElementById('statusFilter').addEventListener('change', loadClues);
            document.getElementById('categoryFilter').addEventListener('change', loadClues);
            document.getElementById('priorityFilter').addEventListener('change', loadClues);
            document.getElementById('startDateFilter').addEventListener('change', loadClues);
            document.getElementById('endDateFilter').addEventListener('change', loadClues);
            
            // 绑定重置按钮事件
            document.getElementById('resetFiltersBtn').addEventListener('click', function() {
                console.log('重置按钮被点击');
                resetFilters();
            });
            
            // 绑定回车搜索
            document.getElementById('keywordSearch').addEventListener('keypress', function(e) {
                if (e.key === 'Enter') {
                    searchClues();
                }
            });

            // === 新增：表格事件委托，处理所有点击 ===
            const tbody = document.getElementById('clueTableBody');
            tbody.addEventListener('click', function(event) {
                const target = event.target;
                // 查看详情（标题链接或按钮）
                if (target.classList.contains('clue-detail-link') || target.classList.contains('clue-detail-btn')) {
                    const clueId = target.getAttribute('data-clue-id');
                    if (clueId) {
                        viewClueDetail(clueId);
                        event.preventDefault();
                    }
                    return;
                }
                // 处理历史按钮
                if (target.classList.contains('clue-history-btn')) {
                    const clueId = target.getAttribute('data-clue-id');
                    if (clueId) {
                        viewProcessingHistory(clueId);
                        event.preventDefault();
                    }
                    return;
                }
                // 更多菜单：状态、优先级
                const a = target.closest('a');
                if (a && a.classList.contains('status-action')) {
                    const clueId = a.getAttribute('data-clue-id');
                    const value = a.getAttribute('data-value');
                    // 弹出状态更新模态框，带入新状态
                    updateClueStatus(clueId, value);
                    event.preventDefault();
                    return;
                }
                if (a && a.classList.contains('priority-action')) {
                    const clueId = a.getAttribute('data-clue-id');
                    const value = a.getAttribute('data-value');
                    setPriority(clueId, value);
                    event.preventDefault();
                    return;
                }
                // 附件预览按钮
                if (target.classList.contains('btn-outline-primary') && target.hasAttribute('data-attachment-id')) {
                    const attachmentId = target.getAttribute('data-attachment-id');
                    const attachmentType = target.getAttribute('data-attachment-type');
                    if (attachmentId && attachmentType) {
                        previewAttachment(attachmentId, attachmentType);
                        event.preventDefault();
                        return;
                    }
                }
            });

            // === 复选框事件委托 ===
            tbody.addEventListener('change', function(event) {
                if (event.target.classList.contains('clue-checkbox')) {
                    updateSelectedClues();
                }
            });

            console.log('=== 页面初始化完成 ===');
            
            // 添加全局测试函数
            window.testExport = function() {
                console.log('测试导出函数');
                exportSelectedClues();
            };
            
            window.testHistory = function(clueId = 1) {
                console.log('测试处理历史函数');
                viewProcessingHistory(clueId);
            };
            
            window.testSelection = function() {
                console.log('当前选中的线索:', selectedClues);
                console.log('选中数量:', selectedClues.length);
            };

            // === 新增：全局事件委托，处理所有附件预览按钮点击 ===
            document.addEventListener('click', function(event) {
                const target = event.target.closest('.btn-outline-primary[data-attachment-id]');
                if (target) {
                    const attachmentId = target.getAttribute('data-attachment-id');
                    const attachmentType = target.getAttribute('data-attachment-type');
                    if (attachmentId && attachmentType) {
                        previewAttachment(attachmentId, attachmentType);
                        event.preventDefault();
                    }
                }
            });

            // 绑定状态更新模态框的确认按钮
            const confirmUpdateBtn = document.getElementById('confirmUpdateBtn');
            if (confirmUpdateBtn) {
                confirmUpdateBtn.addEventListener('click', submitStatusUpdate);
            }
        });

        // 检查认证状态
        function checkAuth() {
            const token = localStorage.getItem('adminToken');
            if (!token) {
                window.location.href = '/admin/login.html';
                return;
            }
            
            const adminUser = JSON.parse(localStorage.getItem('adminUser') || '{}');
            document.getElementById('adminName').textContent = adminUser.real_name || '管理员';
        }

        // 加载线索分类
        async function loadCategories() {
            try {
                const response = await fetch('/api/clue-categories');
                if (response.ok) {
                    const result = await response.json();
                    const categories = result.data || [];
                    
                    const select = document.getElementById('categoryFilter');
                    categories.forEach(category => {
                        const option = document.createElement('option');
                        option.value = category.name;
                        option.textContent = category.name;
                        select.appendChild(option);
                    });
                }
            } catch (error) {
                console.error('加载分类失败:', error);
            }
        }

        // 加载线索列表
        async function loadClues() {
            try {
                const token = localStorage.getItem('adminToken');
                
                // 获取筛选参数
                const startDate = document.getElementById('startDateFilter').value;
                const endDate = document.getElementById('endDateFilter').value;
                
                console.log('加载线索参数:', {
                    page: currentPage,
                    page_size: pageSize,
                    status: document.getElementById('statusFilter').value,
                    category: document.getElementById('categoryFilter').value,
                    priority: document.getElementById('priorityFilter').value,
                    keyword: document.getElementById('keywordSearch').value,
                    start_date: startDate,
                    end_date: endDate
                });
                
                const params = new URLSearchParams({
                    page: currentPage,
                    page_size: pageSize,
                    status: document.getElementById('statusFilter').value,
                    category: document.getElementById('categoryFilter').value,
                    priority: document.getElementById('priorityFilter').value,
                    keyword: document.getElementById('keywordSearch').value,
                    start_date: startDate,
                    end_date: endDate
                });

                const response = await fetch(`/api/admin/clues?${params}`, {
                    headers: {
                        'Authorization': `Bearer ${token}`
                    }
                });

                if (response.status === 401) {
                    window.location.href = '/admin/login.html';
                    return;
                }

                if (response.ok) {
                    const result = await response.json();
                    const data = result.data;
                    
                    console.log('加载线索结果:', data);
                    
                    renderClueTable(data.list || []);
                    renderPagination(data.pagination || {});
                    document.getElementById('totalCount').textContent = data.pagination?.total || 0;
                } else {
                    console.error('加载线索失败:', response.status);
                }
            } catch (error) {
                console.error('加载线索错误:', error);
            }
        }

        // 渲染线索表格
        function renderClueTable(clues) {
            const tbody = document.getElementById('clueTableBody');
            tbody.innerHTML = clues.map(clue => `
                <tr>
                    <td>
                        <input type="checkbox" class="clue-checkbox" value="${clue.id}">
                    </td>
                    <td>
                        <code>${clue.clue_no}</code>
                    </td>
                    <td>
                        <a href="#" class="text-decoration-none clue-detail-link" data-clue-id="${clue.id}">
                            ${clue.title || '无标题'}
                        </a>
                    </td>
                    <td>${clue.category || '-'}</td>
                    <td>
                        <span class="status-badge status-${clue.status}">
                            ${getStatusText(clue.status)}
                        </span>
                    </td>
                    <td>
                        <span class="priority-${clue.priority || 'medium'}">
                            ${getPriorityText(clue.priority)}
                        </span>
                    </td>
                    <td>
                        ${clue.is_anonymous ? '匿名举报' : (clue.reporter_name || '-')}
                        ${clue.reporter_phone ? `<br><small class="text-muted">${clue.reporter_phone}</small>` : ''}
                    </td>
                    <td>
                        <small>${formatDate(clue.created_at)}</small>
                    </td>
                    <td>
                        ${clue.handler_name || '-'}
                    </td>
                    <td>
                        <button class="btn btn-outline-primary btn-action clue-detail-btn" data-clue-id="${clue.id}">
                            <i class="bi bi-eye"></i> 查看
                        </button>
                        <button class="btn btn-outline-info btn-action clue-history-btn" data-clue-id="${clue.id}">
                            <i class="bi bi-clock-history"></i> 处理历史
                        </button>
                        <div class="btn-group">
                            <button class="btn btn-outline-secondary btn-action dropdown-toggle" data-bs-toggle="dropdown">
                                更多
                            </button>
                            <ul class="dropdown-menu">
                                <li><a class="dropdown-item status-action" href="#" data-clue-id="${clue.id}" data-action="status" data-value="processing">
                                    <i class="bi bi-arrow-repeat me-2"></i>处理中
                                </a></li>
                                <li><a class="dropdown-item status-action" href="#" data-clue-id="${clue.id}" data-action="status" data-value="completed">
                                    <i class="bi bi-check-circle me-2"></i>已完成
                                </a></li>
                                <li><a class="dropdown-item status-action" href="#" data-clue-id="${clue.id}" data-action="status" data-value="closed">
                                    <i class="bi bi-x-circle me-2"></i>关闭
                                </a></li>
                                <li><hr class="dropdown-divider"></li>
                                <li><a class="dropdown-item priority-action" href="#" data-clue-id="${clue.id}" data-action="priority" data-value="high">
                                    <i class="bi bi-exclamation-triangle me-2 text-danger"></i>设为高优先级
                                </a></li>
                                <li><a class="dropdown-item priority-action" href="#" data-clue-id="${clue.id}" data-action="priority" data-value="medium">
                                    <i class="bi bi-dash me-2 text-warning"></i>设为中优先级
                                </a></li>
                                <li><a class="dropdown-item priority-action" href="#" data-clue-id="${clue.id}" data-action="priority" data-value="low">
                                    <i class="bi bi-dash-circle me-2 text-secondary"></i>设为低优先级
                                </a></li>
                            </ul>
                        </div>
                    </td>
                </tr>
            `).join('');
            
            // 清空之前的选中状态
            selectedClues = [];
            
            // 重置全选状态
            const selectAll = document.getElementById('selectAll');
            if (selectAll) {
                selectAll.checked = false;
                selectAll.indeterminate = false;
            }
            
            // 更新选中计数显示
            updateSelectedCountDisplay();
        }

        // 渲染分页
        function renderPagination(pagination) {
            const paginationEl = document.getElementById('pagination');
            const { current_page = 1, total_pages = 1 } = pagination;
            
            currentPage = current_page;
            totalPages = total_pages;
            
            let html = '';
            
            // 上一页
            html += `
                <li class="page-item ${current_page <= 1 ? 'disabled' : ''}">
                    <a class="page-link" href="#" onclick="changePage(${current_page - 1})">上一页</a>
                </li>
            `;
            
            // 页码
            const startPage = Math.max(1, current_page - 2);
            const endPage = Math.min(total_pages, current_page + 2);
            
            for (let i = startPage; i <= endPage; i++) {
                html += `
                    <li class="page-item ${i === current_page ? 'active' : ''}">
                        <a class="page-link" href="#" onclick="changePage(${i})">${i}</a>
                    </li>
                `;
            }
            
            // 下一页
            html += `
                <li class="page-item ${current_page >= total_pages ? 'disabled' : ''}">
                    <a class="page-link" href="#" onclick="changePage(${current_page + 1})">下一页</a>
                </li>
            `;
            
            paginationEl.innerHTML = html;
        }

        // 切换页面
        function changePage(page) {
            if (page >= 1 && page <= totalPages) {
                currentPage = page;
                loadClues();
            }
        }

        // 改变每页显示数量
        function changePageSize() {
            pageSize = parseInt(document.getElementById('pageSizeSelect').value);
            currentPage = 1;
            loadClues();
        }

        // 搜索线索
        function searchClues() {
            currentPage = 1;
            loadClues();
        }

        // 重置筛选
        function resetFilters() {
            document.getElementById('statusFilter').value = '';
            document.getElementById('categoryFilter').value = '';
            document.getElementById('priorityFilter').value = '';
            document.getElementById('keywordSearch').value = '';
            document.getElementById('startDateFilter').value = '';
            document.getElementById('endDateFilter').value = '';
            currentPage = 1;
            loadClues();
        }

        // 查看线索详情
        async function viewClueDetail(clueId) {
            console.log('=== 查看线索详情函数被调用 ===');
            console.log('线索ID:', clueId);
            
            try {
                const token = localStorage.getItem('adminToken');
                console.log('Token存在:', !!token);
                
                const url = `/api/admin/clues/${clueId}`;
                console.log('请求URL:', url);
                
                const response = await fetch(url, {
                    headers: {
                        'Authorization': `Bearer ${token}`
                    }
                });

                if (response.status === 401) {
                    window.location.href = '/admin/login.html';
                    return;
                }

                console.log('响应状态:', response.status);
                console.log('响应OK:', response.ok);

                if (response.ok) {
                    const result = await response.json();
                    console.log('响应数据:', result);
                    const clue = result.data;
                    
                    currentClueId = clueId;
                    renderClueDetail(clue);
                    
                    const modal = new bootstrap.Modal(document.getElementById('clueDetailModal'));
                    modal.show();
                } else {
                    const errorText = await response.text();
                    console.error('获取线索详情失败 - 响应:', errorText);
                    alert('获取线索详情失败: ' + response.status);
                }
            } catch (error) {
                console.error('获取线索详情错误:', error);
                alert('获取线索详情失败: ' + error.message);
            }
        }

        // 查看处理历史
        async function viewProcessingHistory(clueId) {
            console.log('=== 查看处理历史函数被调用 ===');
            console.log('线索ID:', clueId);
            
            try {
                console.log('查看处理历史:', clueId);
                currentClueId = clueId;
                
                // 显示模态框
                const modal = new bootstrap.Modal(document.getElementById('processingHistoryModal'));
                modal.show();
                console.log('模态框已显示');
                
                // 加载处理历史
                await loadProcessingHistoryInModal(clueId);
                
            } catch (error) {
                console.error('查看处理历史错误:', error);
                alert('查看处理历史失败: ' + error.message);
            }
        }

        // 在模态框中加载处理历史
        async function loadProcessingHistoryInModal(clueId) {
            console.log('=== 加载处理历史到模态框 ===');
            console.log('线索ID:', clueId);
            
            try {
                const historyContainer = document.getElementById('processingHistoryContent');
                console.log('历史容器元素:', !!historyContainer);
                
                // 显示加载状态
                historyContainer.innerHTML = `
                    <div class="text-center py-3">
                        <div class="spinner-border text-primary" role="status"></div>
                        <p class="mt-2 text-muted">加载处理历史中...</p>
                    </div>
                `;
                
                const token = localStorage.getItem('adminToken');
                console.log('Token存在:', !!token);
                
                const url = `/api/admin/clues/${clueId}/processing-history`;
                console.log('请求URL:', url);
                
                const response = await fetch(url, {
                    headers: {
                        'Authorization': `Bearer ${token}`
                    }
                });

                if (response.status === 401) {
                    window.location.href = '/admin/login.html';
                    return;
                }

                console.log('响应状态:', response.status);
                console.log('响应OK:', response.ok);

                if (response.ok) {
                    const result = await response.json();
                    console.log('处理历史响应数据:', result);
                    const history = result.data.history || [];
                    
                    if (history.length === 0) {
                        historyContainer.innerHTML = `
                            <div class="text-center py-3 text-muted">
                                <i class="bi bi-clock-history fs-4"></i>
                                <p class="mt-2">暂无处理历史</p>
                            </div>
                        `;
                        return;
                    }
                    
                    historyContainer.innerHTML = `
                        <div class="timeline">
                            ${history.map(record => `
                                <div class="timeline-item">
                                    <div class="timeline-marker">
                                        <i class="bi ${getActionIcon(record.action_type)}"></i>
                                    </div>
                                    <div class="timeline-content">
                                        <div class="d-flex justify-content-between align-items-start">
                                            <div class="flex-grow-1">
                                                <h6 class="mb-1">${record.action_text}</h6>
                                                ${record.old_value && record.new_value ? `
                                                    <p class="mb-1 text-muted small">
                                                        ${getStatusText(record.old_value)} → ${getStatusText(record.new_value)}
                                                    </p>
                                                ` : ''}
                                                ${record.processing_opinion ? `
                                                    <div class="bg-light p-2 rounded mt-2">
                                                        <strong>处理意见：</strong>${record.processing_opinion}
                                                    </div>
                                                ` : ''}
                                                ${record.note ? `
                                                    <div class="text-muted small mt-1">
                                                        <strong>备注：</strong>${record.note}
                                                    </div>
                                                ` : ''}
                                            </div>
                                            <small class="text-muted ms-3">
                                                ${record.formatted_time}<br>
                                                <span class="text-primary">${record.admin_name}</span>
                                            </small>
                                        </div>
                                    </div>
                                </div>
                            `).join('')}
                        </div>
                    `;
                } else {
                    const errorText = await response.text();
                    console.error('加载处理历史失败 - 响应:', errorText);
                    historyContainer.innerHTML = `
                        <div class="text-center py-3 text-danger">
                            <i class="bi bi-exclamation-triangle fs-4"></i>
                            <p class="mt-2">加载处理历史失败: ${response.status}</p>
                        </div>
                    `;
                }
            } catch (error) {
                console.error('加载处理历史失败:', error);
                document.getElementById('processingHistoryContent').innerHTML = `
                    <div class="text-center py-3 text-danger">
                        <i class="bi bi-exclamation-triangle fs-4"></i>
                        <p class="mt-2">加载处理历史失败: ${error.message}</p>
                    </div>
                `;
            }
        }

        // 添加处理意见
        function addProcessingNote() {
            if (currentClueId) {
                // 关闭处理历史模态框
                bootstrap.Modal.getInstance(document.getElementById('processingHistoryModal')).hide();
                // 打开状态更新模态框
                updateClueStatus(currentClueId);
            }
        }

        // 渲染线索详情
        function renderClueDetail(clue) {
            const content = document.getElementById('clueDetailContent');
            content.innerHTML = `
                <div class="row">
                    <div class="col-md-6">
                        <h6>基本信息</h6>
                        <table class="table table-sm">
                            <tr><td>线索编号:</td><td><code>${clue.clue_no}</code></td></tr>
                            <tr><td>线索标题:</td><td>${clue.title || '-'}</td></tr>
                            <tr><td>线索分类:</td><td>${clue.category || '-'}</td></tr>
                            <tr><td>当前状态:</td><td><span class="status-badge status-${clue.status}">${getStatusText(clue.status)}</span></td></tr>
                            <tr><td>优先级:</td><td><span class="priority-${clue.priority || 'medium'}">${getPriorityText(clue.priority)}</span></td></tr>
                            <tr><td>提交时间:</td><td>${formatDate(clue.created_at)}</td></tr>
                            <tr><td>更新时间:</td><td>${formatDate(clue.updated_at)}</td></tr>
                        </table>
                    </div>
                    <div class="col-md-6">
                        <h6>举报人信息</h6>
                        <table class="table table-sm">
                            <tr><td>举报方式:</td><td>${clue.is_anonymous ? '匿名举报' : '实名举报'}</td></tr>
                            <tr><td>姓名:</td><td>${clue.is_anonymous ? '匿名' : (clue.reporter_name || '-')}</td></tr>
                            <tr><td>联系电话:</td><td>${clue.is_anonymous ? '匿名' : (clue.reporter_phone || '-')}</td></tr>
                            <tr><td>邮箱:</td><td>${clue.is_anonymous ? '匿名' : (clue.reporter_email || '-')}</td></tr>
                            <tr><td>地区:</td><td>${clue.province || ''} ${clue.city || ''} ${clue.district || ''}</td></tr>
                            <tr><td>详细地址:</td><td>${clue.address || '-'}</td></tr>
                        </table>
                    </div>
                </div>
                
                <div class="row mt-3">
                    <div class="col-12">
                        <h6>案情描述</h6>
                        <div class="border rounded p-3 bg-light">
                            ${clue.content || '无详细描述'}
                        </div>
                    </div>
                </div>
                
                ${clue.suspect_info ? `
                <div class="row mt-3">
                    <div class="col-12">
                        <h6>涉案人员信息</h6>
                        <div class="border rounded p-3 bg-light">
                            ${clue.suspect_info}
                        </div>
                    </div>
                </div>
                ` : ''}
                
                <div class="row mt-3">
                    <div class="col-md-6">
                        <h6>案发信息</h6>
                        <table class="table table-sm">
                            <tr><td>案发时间:</td><td>${clue.incident_time || '未知'}</td></tr>
                            <tr><td>案发地点:</td><td>${clue.incident_location || '未知'}</td></tr>
                        </table>
                    </div>
                    <div class="col-md-6">
                        <h6>处理信息</h6>
                        <table class="table table-sm">
                            <tr><td>处理人:</td><td>${clue.handler_name || '未分配'}</td></tr>
                            <tr><td>查看次数:</td><td>${clue.view_count || 0}</td></tr>
                        </table>
                    </div>
                </div>
                
                ${clue.attachments && clue.attachments.length > 0 ? `
                <div class="row mt-3">
                    <div class="col-12">
                        <h6>附件列表 <span class="badge bg-secondary">${clue.attachments.length}</span></h6>
                        <div class="row g-3">
                            ${clue.attachments.map(att => renderAttachmentItem(att)).join('')}
                        </div>
                    </div>
                </div>
                ` : ''}
            `;
            
            // 自动加载处理历史
            // setTimeout(() => loadProcessingHistory(clue.id), 500);
        }

        // 渲染附件项目
        function renderAttachmentItem(attachment) {
            const isImage = attachment.file_type && attachment.file_type.startsWith('image/');
            const isVideo = attachment.file_type && attachment.file_type.startsWith('video/');
            const isAudio = attachment.file_type && attachment.file_type.startsWith('audio/');
            const isPdf = attachment.file_type === 'application/pdf';
            // 获取token
            const token = localStorage.getItem('adminToken') || '';
            function withToken(url) {
                if (!token) return url;
                return url + (url.includes('?') ? '&' : '?') + 'token=' + encodeURIComponent(token);
            }
            // 获取文件图标
            let fileIcon = 'bi-file-earmark';
            if (isImage) fileIcon = 'bi-file-earmark-image';
            else if (isVideo) fileIcon = 'bi-file-earmark-play';
            else if (isAudio) fileIcon = 'bi-file-earmark-music';
            else if (isPdf) fileIcon = 'bi-file-earmark-pdf';
            else if (attachment.file_type && attachment.file_type.includes('word')) fileIcon = 'bi-file-earmark-word';
            else if (attachment.file_type && attachment.file_type.includes('excel')) fileIcon = 'bi-file-earmark-excel';

            return `
                <div class="card h-100">
                    <div class="card-body">
                        <div class="d-flex align-items-start">
                            <i class="bi ${fileIcon} fs-3 text-primary me-3"></i>
                            <div class="flex-grow-1">
                                <h6 class="card-title mb-1" title="${attachment.file_name}">${attachment.file_name.length > 20 ? attachment.file_name.substring(0, 20) + '...' : attachment.file_name}</h6>
                                <p class="card-text text-muted small mb-2">
                                    大小: ${formatFileSize(attachment.file_size)}<br>
                                    上传时间: ${formatDate(attachment.upload_time)}
                                </p>
                                ${isImage ? `
                                <div class="mb-2">
                                    <img src="${withToken('/api/admin/attachments/' + attachment.id + '/view')}" 
                                         class="img-thumbnail" 
                                         style="max-width: 150px; max-height: 100px; cursor: pointer;"
                                         onerror="this.style.display='none'"
                                         alt="图片预览">
                                </div>
                                ` : ''}
                                ${isVideo ? `
                                <div class="mb-2">
                                    <video width="150" height="100" controls style="max-width: 100%;">
                                        <source src="${withToken('/api/admin/attachments/' + attachment.id + '/view')}" type="${attachment.file_type}">
                                        您的浏览器不支持视频播放
                                    </video>
                                </div>
                                ` : ''}
                                ${isAudio ? `
                                <div class="mb-2">
                                    <audio controls style="width: 100%; max-width: 200px;">
                                        <source src="${withToken('/api/admin/attachments/' + attachment.id + '/view')}" type="${attachment.file_type}">
                                        您的浏览器不支持音频播放
                                    </audio>
                                </div>
                                ` : ''}
                                <div class="btn-group btn-group-sm w-100">
                                    ${(isImage || isVideo || isAudio || isPdf) ? `
                                    <button class="btn btn-outline-primary" 
                                            data-attachment-id="${attachment.id}"
                                            data-attachment-type="${isImage ? 'image' : isVideo ? 'video' : isAudio ? 'audio' : isPdf ? 'pdf' : 'other'}">
                                        <i class="bi bi-eye"></i> 预览
                                    </button>
                                    ` : ''}
                                    <a href="${withToken('/api/admin/attachments/' + attachment.id + '/download')}" 
                                       class="btn btn-outline-success" 
                                       download="${attachment.file_name}">
                                    <i class="bi bi-download"></i> 下载
                                </a>
                            </div>
                    </div>
                </div>
            </div>
                </div>
            `;
        }

        // 预览附件
        function previewAttachment(attachmentId, type) {
            const token = localStorage.getItem('adminToken') || '';
            function withToken(url) {
                if (!token) return url;
                return url + (url.includes('?') ? '&' : '?') + 'token=' + encodeURIComponent(token);
            }
            const modalHtml = `
                <div class="modal fade" id="attachmentPreviewModal" tabindex="-1">
                    <div class="modal-dialog modal-xl modal-dialog-centered">
                        <div class="modal-content">
                            <div class="modal-header">
                                <h5 class="modal-title">附件预览</h5>
                                <button type="button" class="btn-close" data-bs-dismiss="modal"></button>
                            </div>
                            <div class="modal-body text-center">
                                <div id="previewContent">
                                    <div class="spinner-border text-primary" role="status">
                                        <span class="visually-hidden">加载中...</span>
                                    </div>
                                </div>
                            </div>
                            <div class="modal-footer">
                                <a href="${withToken('/api/admin/attachments/' + attachmentId + '/download')}" 
                                   class="btn btn-success" download>
                                    <i class="bi bi-download"></i> 下载
                                </a>
                                <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">关闭</button>
                            </div>
                        </div>
                    </div>
                </div>
            `;
            
            // 移除已存在的模态框
            const existingModal = document.getElementById('attachmentPreviewModal');
            if (existingModal) {
                existingModal.remove();
            }
            
            // 添加新模态框
            document.body.insertAdjacentHTML('beforeend', modalHtml);
            
            const modal = new bootstrap.Modal(document.getElementById('attachmentPreviewModal'));
            modal.show();
            
            // 加载预览内容
            loadPreviewContent(attachmentId, type);
        }

        // 加载预览内容
        async function loadPreviewContent(attachmentId, type) {
            try {
                const previewContent = document.getElementById('previewContent');
                const token = localStorage.getItem('adminToken') || '';
                function withToken(url) {
                    if (!token) return url;
                    return url + (url.includes('?') ? '&' : '?') + 'token=' + encodeURIComponent(token);
                }
                const viewUrl = withToken(`/api/admin/attachments/${attachmentId}/view`);
                
                switch (type) {
                    case 'image':
                        previewContent.innerHTML = `
                            <img src="${viewUrl}" 
                                 class="img-fluid preview-max" 
                                 style="max-width:100vw; max-height:80vh; display:block; margin:auto;"
                                 alt="图片预览">
                        `;
                        break;
                        
                    case 'video':
                        previewContent.innerHTML = `
                            <video controls style="max-width:100vw; max-height:80vh; display:block; margin:auto;">
                                <source src="${viewUrl}" type="video/mp4">
                                <source src="${viewUrl}" type="video/webm">
                                <source src="${viewUrl}" type="video/ogg">
                                您的浏览器不支持视频播放
                            </video>
                        `;
                        break;
                        
                    case 'audio':
                        previewContent.innerHTML = `
                            <div class="p-4">
                                <i class="bi bi-music-note-beamed fs-1 text-primary mb-3"></i>
                                <br>
                                <audio controls style="width:100%; max-width:600px; display:block; margin:auto;">
                                    <source src="${viewUrl}" type="audio/mpeg">
                                    <source src="${viewUrl}" type="audio/wav">
                                    <source src="${viewUrl}" type="audio/ogg">
                                    您的浏览器不支持音频播放
                                </audio>
                            </div>
                        `;
                        break;
                        
                    case 'pdf':
                        previewContent.innerHTML = `
                            <iframe src="${viewUrl}" 
                                    style="width:100vw; max-width:100%; height:80vh; border:none; display:block; margin:auto;">
                                您的浏览器不支持PDF预览，请<a href="${viewUrl}" target="_blank">点击这里</a>在新窗口中查看
                            </iframe>
                        `;
                        break;
                        
                    default:
                        previewContent.innerHTML = `
                            <div class="p-4">
                                <i class="bi bi-file-earmark fs-1 text-muted mb-3"></i>
                                <p class="text-muted">此文件类型不支持预览</p>
                                <a href="${viewUrl}" target="_blank" class="btn btn-primary">
                                    <i class="bi bi-box-arrow-up-right"></i> 在新窗口中打开
                                </a>
                            </div>
                        `;
                }
            } catch (error) {
                console.error('加载预览内容失败:', error);
                document.getElementById('previewContent').innerHTML = `
                    <div class="p-4">
                        <i class="bi bi-exclamation-triangle fs-1 text-danger mb-3"></i>
                        <p class="text-danger">预览加载失败</p>
                    </div>
                `;
            }
        }

        // 更新线索状态
        function updateClueStatus(clueId, newStatus) {
            currentClueId = clueId;
            // 重置模态框
            resetUpdateModal();
            document.getElementById('updateClueId').value = clueId;
            if (newStatus) {
                document.getElementById('newStatus').value = newStatus;
            }
            const modal = new bootstrap.Modal(document.getElementById('statusUpdateModal'));
            modal.show();
        }

        // 提交状态更新
        async function submitStatusUpdate() {
            try {
                const clueId = document.getElementById('updateClueId').value;
                const status = document.getElementById('newStatus').value;
                const handleNote = document.getElementById('handleNote').value;
                const resultDiv = document.getElementById('statusUpdateResult');
                const confirmBtn = document.getElementById('confirmUpdateBtn');
                
                if (!status) {
                    showUpdateResult('请选择新状态', 'danger');
                    return;
                }
                
                // 显示处理中状态
                confirmBtn.disabled = true;
                confirmBtn.innerHTML = '<i class="bi bi-hourglass-split me-2"></i>处理中...';
                
                const token = localStorage.getItem('adminToken');
                const response = await fetch(`/api/admin/clues/${clueId}/status`, {
                    method: 'PUT',
                    headers: {
                        'Content-Type': 'application/json',
                        'Authorization': `Bearer ${token}`
                    },
                    body: JSON.stringify({
                        status,
                        handle_note: handleNote
                    })
                });

                if (response.status === 401) {
                    window.location.href = '/admin/login.html';
                    return;
                }

                const result = await response.json();
                
                if (response.ok) {
                    showUpdateResult('状态更新成功！', 'success');
                    
                    // 延迟关闭模态框并刷新列表
                    setTimeout(() => {
                    bootstrap.Modal.getInstance(document.getElementById('statusUpdateModal')).hide();
                    loadClues();
                        resetUpdateModal();
                    }, 1500);
                } else {
                    showUpdateResult(result.message || '状态更新失败', 'danger');
                    resetUpdateButton();
                }
            } catch (error) {
                console.error('状态更新错误:', error);
                showUpdateResult('状态更新失败：网络错误', 'danger');
                resetUpdateButton();
            }
        }
        
        // 显示更新结果
        function showUpdateResult(message, type) {
            const resultDiv = document.getElementById('statusUpdateResult');
            resultDiv.className = `alert alert-${type}`;
            resultDiv.textContent = message;
            resultDiv.style.display = 'block';
        }
        
        // 重置更新按钮
        function resetUpdateButton() {
            const confirmBtn = document.getElementById('confirmUpdateBtn');
            confirmBtn.disabled = false;
            confirmBtn.innerHTML = '确认更新';
        }
        
        // 重置更新模态框
        function resetUpdateModal() {
            document.getElementById('updateClueId').value = '';
            document.getElementById('newStatus').value = '';
            document.getElementById('handleNote').value = '';
            document.getElementById('statusUpdateResult').style.display = 'none';
            resetUpdateButton();
        }

        // 快速设置状态
        async function setClueStatus(clueId, status) {
            console.log('设置状态请求:', { clueId, status });
            
            if (!confirm(`确认将线索状态设置为"${getStatusText(status)}"吗？`)) {
                return;
            }
            
            try {
                const token = localStorage.getItem('adminToken');
                console.log('发送状态更新请求:', {
                    url: `/api/admin/clues/${clueId}/status`,
                    method: 'PUT',
                    body: { status }
                });
                
                const response = await fetch(`/api/admin/clues/${clueId}/status`, {
                    method: 'PUT',
                    headers: {
                        'Content-Type': 'application/json',
                        'Authorization': `Bearer ${token}`
                    },
                    body: JSON.stringify({ status })
                });

                if (response.status === 401) {
                    window.location.href = '/admin/login.html';
                    return;
                }

                const result = await response.json();
                console.log('状态更新响应:', { status: response.status, result });
                
                if (response.ok) {
                    alert('状态更新成功');
                    loadClues();
                } else {
                    console.error('状态更新失败:', result);
                    alert(result.message || '状态更新失败');
                }
            } catch (error) {
                console.error('状态更新错误:', error);
                alert('状态更新失败：网络错误');
            }
        }

        // 全选/取消全选
        function toggleSelectAll() {
            try {
            const selectAll = document.getElementById('selectAll');
            const checkboxes = document.querySelectorAll('.clue-checkbox');
                
                if (!selectAll || checkboxes.length === 0) {
                    console.warn('全选元素或复选框不存在');
                    return;
                }
            
            checkboxes.forEach(checkbox => {
                checkbox.checked = selectAll.checked;
            });
            
            updateSelectedClues();
            } catch (error) {
                console.error('全选切换失败:', error);
            }
        }

        // 更新选中的线索
        function updateSelectedClues() {
            try {
            const checkboxes = document.querySelectorAll('.clue-checkbox:checked');
            selectedClues = Array.from(checkboxes).map(cb => cb.value);
            
            // 更新全选状态
            const selectAll = document.getElementById('selectAll');
            const allCheckboxes = document.querySelectorAll('.clue-checkbox');
                
                if (selectAll && allCheckboxes.length > 0) {
            selectAll.checked = selectedClues.length === allCheckboxes.length;
            selectAll.indeterminate = selectedClues.length > 0 && selectedClues.length < allCheckboxes.length;
                }
                
                // 更新选中计数显示
                updateSelectedCountDisplay();
            } catch (error) {
                console.error('更新选中状态失败:', error);
            }
        }
        
        // 更新选中数量显示
        function updateSelectedCountDisplay() {
            try {
                const selectedCountBadge = document.getElementById('selectedCountBadge');
                const exportSelectedBtn = document.getElementById('exportBtn');
                const clearSelectionBtn = document.getElementById('clearSelectionBtn');
                const clearSelectionBadge = document.getElementById('clearSelectionBadge');
                const batchActionsGroup = document.getElementById('batchActionsGroup');
                
                const hasSelection = selectedClues.length > 0;
                
                if (selectedCountBadge) {
                    selectedCountBadge.textContent = selectedClues.length;
                    
                    // 根据选中数量更新徽章样式
                    selectedCountBadge.className = hasSelection ? 
                        'badge bg-primary ms-1' : 'badge bg-secondary ms-1';
                }
                
                // 更新导出选中按钮的状态
                if (exportSelectedBtn) {
                    if (hasSelection) {
                        exportSelectedBtn.classList.remove('disabled');
                        exportSelectedBtn.style.opacity = '1';
                    } else {
                        exportSelectedBtn.classList.add('disabled');
                        exportSelectedBtn.style.opacity = '0.6';
                    }
                }
                
                // 更新清空选择按钮的显示
                if (clearSelectionBtn && clearSelectionBadge) {
                    if (hasSelection) {
                        clearSelectionBadge.textContent = selectedClues.length;
                        clearSelectionBtn.style.display = 'inline-block';
                    } else {
                        clearSelectionBtn.style.display = 'none';
                    }
                }
                
                // 更新批量操作区域的样式
                if (batchActionsGroup) {
                    if (hasSelection) {
                        batchActionsGroup.classList.add('has-selection');
                    } else {
                        batchActionsGroup.classList.remove('has-selection');
                    }
                }
            } catch (error) {
                console.error('更新选中计数显示失败:', error);
            }
        }

        // 批量更新状态
        async function batchUpdateStatus(status) {
            if (selectedClues.length === 0) {
                alert('请先选择要操作的线索');
                return;
            }
            
            if (!confirm(`确认将选中的 ${selectedClues.length} 条线索状态设置为"${getStatusText(status)}"吗？`)) {
                return;
            }
            
            try {
                const token = localStorage.getItem('adminToken');
                console.log('发送批量更新请求:', {
                    action: 'update_status',
                    clue_ids: selectedClues,
                    data: { status }
                });
                
                const response = await fetch('/api/admin/clues/batch', {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/json',
                        'Authorization': `Bearer ${token}`
                    },
                    body: JSON.stringify({
                        action: 'update_status',
                        clue_ids: selectedClues,
                        data: { status }
                    })
                });

                if (response.status === 401) {
                    window.location.href = '/admin/login.html';
                    return;
                }

                const result = await response.json();
                console.log('批量更新响应:', result);
                
                if (response.ok) {
                    alert(`批量更新成功，共更新了 ${result.data?.affected_rows || selectedClues.length} 条线索`);
                    clearSelection();
                    loadClues();
                } else {
                    console.error('批量更新失败:', result);
                    alert(result.message || '批量更新失败');
                }
            } catch (error) {
                console.error('批量更新错误:', error);
                alert('批量更新失败：网络错误');
            }
        }
        
        // 清空选中状态
        function clearSelection() {
            try {
                selectedClues = [];
                
                const selectAll = document.getElementById('selectAll');
                if (selectAll) {
                    selectAll.checked = false;
                    selectAll.indeterminate = false;
                }
                
                // 清空所有复选框
                document.querySelectorAll('.clue-checkbox').forEach(checkbox => {
                    checkbox.checked = false;
                });
                
                updateSelectedCountDisplay();
            } catch (error) {
                console.error('清空选择失败:', error);
            }
        }

        // 导出数据
        function exportSelectedClues() {
            console.log('=== 导出函数被调用 ===');
            console.log('当前选中的线索:', selectedClues);
            
            try {
                console.log('开始导出数据...', { scope: 'selected', format: 'excel' });
                
                if (selectedClues.length === 0) {
                    console.warn('没有选中的线索');
                    alert('请先选择要导出的线索');
                    return;
                }
                console.log('导出选中的线索:', selectedClues);
                
                const params = new URLSearchParams({
                    format: 'excel'
                });
                
                params.append('clue_ids', selectedClues.join(','));
            
                const token = localStorage.getItem('adminToken');
                if (!token) {
                    console.error('没有认证令牌');
                    alert('请先登录');
                    return;
                }
                
                console.log('导出参数:', {
                    scope: 'selected',
                    format: 'excel',
                    selectedCount: selectedClues.length,
                    params: Object.fromEntries(params.entries())
                });
                
                // 获取按钮元素并设置加载状态
                const exportBtn = document.getElementById('exportBtn');
                let originalText = '';
                let loadingText = '';
                
                if (exportBtn) {
                    originalText = exportBtn.innerHTML;
                    loadingText = `<i class="bi bi-hourglass-split me-2"></i>导出中...`;
                    exportBtn.innerHTML = loadingText;
                    exportBtn.disabled = true;
                }
                
                // 创建下载链接，直接触发下载
                const exportUrl = `/api/admin/clues/export?${params}&token=${encodeURIComponent(token)}`;
                console.log('导出URL:', exportUrl);
                
                // 创建一个隐藏的iframe来处理下载
                const iframe = document.createElement('iframe');
                iframe.style.display = 'none';
                iframe.src = exportUrl;
                
                // 添加错误处理
                iframe.onerror = function() {
                    console.error('iframe下载失败');
                    alert('导出失败，请稍后重试');
                    
                    // 恢复按钮状态
                    if (exportBtn) {
                        exportBtn.innerHTML = originalText;
                        exportBtn.disabled = false;
                    }
                };
                
                // 添加加载完成处理
                iframe.onload = function() {
                    console.log('iframe加载完成');
                    
                    // 延迟移除iframe和恢复按钮状态
                    setTimeout(() => {
                        if (iframe && iframe.parentNode) {
                            iframe.parentNode.removeChild(iframe);
                        }
                        
                        if (exportBtn) {
                            exportBtn.innerHTML = originalText;
                            exportBtn.disabled = false;
                        }
                    }, 3000);
                };
                
                document.body.appendChild(iframe);
                console.log('导出iframe已添加到页面');
                
            } catch (error) {
                console.error('导出失败:', error);
                alert('导出失败：' + error.message);
                
                // 恢复按钮状态
                const exportButton = document.getElementById('exportBtn');
                if (exportButton) {
                    exportButton.innerHTML = '<i class="bi bi-download me-2"></i>导出选中数据 <span class="badge bg-light text-dark ms-1" id="selectedCountBadge">0</span>';
                    exportButton.disabled = false;
                }
            }
        }

        // 编辑线索（从详情模态框调用）
        function editClue() {
            if (currentClueId) {
                updateClueStatus(currentClueId);
                // 关闭详情模态框
                bootstrap.Modal.getInstance(document.getElementById('clueDetailModal')).hide();
            }
        }

        // 设置优先级
        async function setPriority(clueId, priority) {
            // 将字符串优先级转换为数值
            const priorityMap = {
                'high': 3,
                'medium': 2, 
                'low': 1
            };
            
            const priorityValue = priorityMap[priority];
            if (!priorityValue) {
                alert('无效的优先级值');
                return;
            }
            
            if (!confirm(`确认将线索优先级设置为"${getPriorityText(priority)}"吗？`)) {
                return;
            }
            
            try {
                const token = localStorage.getItem('adminToken');
                console.log('设置优先级请求:', { clueId, priority: priorityValue });
                
                const response = await fetch(`/api/admin/clues/${clueId}`, {
                    method: 'PUT',
                    headers: {
                        'Content-Type': 'application/json',
                        'Authorization': `Bearer ${token}`
                    },
                    body: JSON.stringify({ priority: priorityValue })
                });

                if (response.status === 401) {
                    window.location.href = '/admin/login.html';
                    return;
                }

                const result = await response.json();
                console.log('设置优先级响应:', result);
                
                if (response.ok) {
                    alert('优先级更新成功');
                    loadClues();
                } else {
                    console.error('优先级更新失败:', result);
                    alert(result.message || '优先级更新失败');
                }
            } catch (error) {
                console.error('优先级更新错误:', error);
                alert('优先级更新失败：网络错误');
            }
        }

        // 工具函数
        function getStatusText(status) {
            const statusMap = {
                'pending': '待处理',
                'processing': '处理中',
                'completed': '已完成',
                'closed': '已关闭'
            };
            return statusMap[status] || status;
        }

        function getPriorityText(priority) {
            // 处理数值类型的优先级
            if (typeof priority === 'number') {
                const numPriorityMap = {
                    3: '高',
                    2: '中',
                    1: '低'
                };
                return numPriorityMap[priority] || '中';
            }
            
            // 处理字符串类型的优先级
            const priorityMap = {
                'high': '高',
                'medium': '中',
                'low': '低'
            };
            return priorityMap[priority] || '中';
        }

        function formatDate(dateString) {
            if (!dateString) return '-';
            const date = new Date(dateString);
            return date.toLocaleString('zh-CN');
        }

        function formatFileSize(bytes) {
            if (bytes === 0) return '0 B';
            const k = 1024;
            const sizes = ['B', 'KB', 'MB', 'GB'];
            const i = Math.floor(Math.log(bytes) / Math.log(k));
            return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
        }

        // 退出登录
        function logout() {
            localStorage.removeItem('adminToken');
            localStorage.removeItem('adminUser');
            window.location.href = '/admin/login.html';
        }

        // 获取操作图标
        function getActionIcon(actionType) {
            const iconMap = {
                'status_change': 'bi-arrow-repeat',
                'priority_change': 'bi-flag',
                'assignment': 'bi-person-check',
                'note_added': 'bi-chat-text',
                'file_uploaded': 'bi-file-earmark-plus'
            };
            return iconMap[actionType] || 'bi-clock-history';
        }

        // 加载详情弹窗中的处理历史
        async function loadProcessingHistory(clueId) {
            const historyContainer = document.getElementById('processingHistory');
            if (!historyContainer) return;
            historyContainer.innerHTML = `
                <div class="text-center py-3">
                    <div class="spinner-border text-primary" role="status"></div>
                    <p class="mt-2 text-muted">加载处理历史中...</p>
                </div>
            `;
            try {
                const token = localStorage.getItem('adminToken');
                const url = `/api/admin/clues/${clueId}/processing-history`;
                const response = await fetch(url, {
                    headers: { 'Authorization': `Bearer ${token}` }
                });

                if (response.status === 401) {
                    window.location.href = '/admin/login.html';
                    return;
                }

                if (response.ok) {
                    const result = await response.json();
                    const history = result.data.history || [];
                    if (history.length === 0) {
                        historyContainer.innerHTML = `
                            <div class="text-center py-3 text-muted">
                                <i class="bi bi-clock-history fs-4"></i>
                                <p class="mt-2">暂无处理历史</p>
                            </div>
                        `;
                        return;
                    }
                    historyContainer.innerHTML = `
                        <div class="timeline">
                            ${history.map(record => `
                                <div class="timeline-item">
                                    <div class="timeline-marker">
                                        <i class="bi ${getActionIcon(record.action_type)}"></i>
                                    </div>
                                    <div class="timeline-content">
                                        <div class="d-flex justify-content-between align-items-start">
                                            <div class="flex-grow-1">
                                                <h6 class="mb-1">${record.action_text}</h6>
                                                ${record.old_value && record.new_value ? `
                                                    <p class="mb-1 text-muted small">
                                                        ${getStatusText(record.old_value)} → ${getStatusText(record.new_value)}
                                                    </p>
                                                ` : ''}
                                                ${record.processing_opinion ? `
                                                    <div class="bg-light p-2 rounded mt-2">
                                                        <strong>处理意见：</strong>${record.processing_opinion}
                                                    </div>
                                                ` : ''}
                                                ${record.note ? `
                                                    <div class="text-muted small mt-1">
                                                        <strong>备注：</strong>${record.note}
                                                    </div>
                                                ` : ''}
                                            </div>
                                            <small class="text-muted ms-3">
                                                ${record.formatted_time}<br>
                                                <span class="text-primary">${record.admin_name}</span>
                                            </small>
                                        </div>
                                    </div>
                                </div>
                            `).join('')}
                        </div>
                    `;
                } else {
                    historyContainer.innerHTML = `
                        <div class="text-center py-3 text-danger">
                            <i class="bi bi-exclamation-triangle fs-4"></i>
                            <p class="mt-2">加载处理历史失败: ${response.status}</p>
                        </div>
                    `;
                }
            } catch (error) {
                historyContainer.innerHTML = `
                    <div class="text-center py-3 text-danger">
                        <i class="bi bi-exclamation-triangle fs-4"></i>
                        <p class="mt-2">加载处理历史失败: ${error.message}</p>
                    </div>
                `;
            }
        }
    </script>
</body>
</html> 